package br.com.winesys.geta;

import java.awt.Dimension;
import java.awt.Window;
import java.util.Map;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.PersistenceUnit;
import javax.swing.JPanel;
import br.com.winesys.geta.crud.CadastroAction;
import br.com.winesys.geta.crud.CadastroPopup;
import br.com.winesys.geta.crud.CadastroTabela;
import br.com.winesys.geta.crud.CadastroUnico;
import br.com.winesys.geta.crud.JPACadastroPopup;
import br.com.winesys.geta.crud.JPACadastroTabela;
import br.com.winesys.geta.crud.JPACadastroUnico;
import br.com.winesys.geta.databinding.component.selector.ObjectSelector;
import br.com.winesys.geta.databinding.component.table.TableModel;
import br.com.winesys.geta.editor.Editor;

final class CadastroBuilder {

	private CadastroBuilder() {
	}

	public static <T> CadastroUnico<T> createCadastroUnico(final Class<T> entityClass, final Window owner, final String title) {
		final PersistenceUnit pu = entityClass.getAnnotation(PersistenceUnit.class);
		if (pu == null) {
			throw new IllegalArgumentException(String.format("Class %s is not marked with @PersistenceUnit", entityClass.getSimpleName()));
		}
		return new JPACadastroUnico<T>(owner, title) {

			@Override
			protected String getPersistenceUnit() {
				return pu.name();
			}

			@Override
			protected T createNewObject() {
				try {
					return entityClass.newInstance();
				} catch (Exception ex) {
					throw new RuntimeException(String.format("Unable to create a new instance of %s", entityClass.getSimpleName()));
				}
			}

			@Override
			protected ObjectSelector<T> createObjectSelector() {
				return ObjectSelectorBuilder.createSelector(entityClass);
			}

			@Override
			protected Editor<T> createObjectEditor() {
				return ObjectEditorBuilder.createEditor(entityClass);
			}
		};
	}

	public static <T> CadastroPopup<T> createCadastroPopup(final Class<T> entityClass, final Window owner, final String title, final Dimension dimension) {
		final PersistenceUnit pu = entityClass.getAnnotation(PersistenceUnit.class);
		if (pu == null) {
			throw new IllegalArgumentException(String.format("Class %s is not marked with @PersistenceUnit", entityClass.getSimpleName()));
		}
		final NamedQueries queries = entityClass.getAnnotation(NamedQueries.class);
		NamedQuery listQuery = null;
		for (NamedQuery query : queries.value()) {
			if (query.name().equalsIgnoreCase(String.format("%s.listCRUD", entityClass.getSimpleName()))) {
				listQuery = query;
			}
		}
		if (listQuery == null) {
			throw new IllegalArgumentException(String.format("Class %s doesn't have @NamedQuery named %s.listCRUD", entityClass.getSimpleName(), entityClass.getSimpleName()));
		}
		final NamedQuery fListQuery = listQuery;
		return new JPACadastroPopup<T>(owner, title, dimension) {

			@Override
			protected String getPersistenceUnit() {
				return pu.name();
			}

			@Override
			protected String getListQuery(Map<String, Object> params) {
				return fListQuery.query();
			}

			@Override
			protected T createNewObject() {
				try {
					return entityClass.newInstance();
				} catch (Exception ex) {
					throw new RuntimeException(String.format("Unable to create a new instance of %s", entityClass.getSimpleName()));
				}
			}

			@Override
			protected Editor<T> createObjectEditor(CadastroAction action) {
				return ObjectEditorBuilder.createEditor(entityClass);
			}

			@Override
			protected Editor<?> createFilter() {
				return null;
			}

			@Override
			protected TableModel<T> createTableModel() {
				return TableModelBuilder.createTableModel(entityClass);
			}
		};
	}

	public static <T> CadastroTabela<T> createCadastroTabela(final Class<T> entityClass, final Window owner, final String title, final Dimension dimension) {
		final PersistenceUnit pu = entityClass.getAnnotation(PersistenceUnit.class);
		if (pu == null) {
			throw new IllegalArgumentException(String.format("Class %s is not marked with @PersistenceUnit", entityClass.getSimpleName()));
		}
		final NamedQueries queries = entityClass.getAnnotation(NamedQueries.class);
		NamedQuery listQuery = null;
		for (NamedQuery query : queries.value()) {
			if (query.name().equalsIgnoreCase(String.format("%s.listCRUD", entityClass.getSimpleName()))) {
				listQuery = query;
			}
		}
		if (listQuery == null) {
			throw new IllegalArgumentException(String.format("Class %s doesn't have @NamedQuery named %s.listCRUD", entityClass.getSimpleName(), entityClass.getSimpleName()));
		}
		final NamedQuery fListQuery = listQuery;
		return new JPACadastroTabela<T>(owner, title, dimension) {

			@Override
			protected String getPersistenceUnit() {
				return pu.name();
			}

			@Override
			protected String getListQuery(Map<String, Object> params) {
				return fListQuery.query();
			}

			@Override
			protected T createNewObject() {
				try {
					return entityClass.newInstance();
				} catch (Exception ex) {
					throw new RuntimeException(String.format("Unable to create a new instance of %s", entityClass.getSimpleName()));
				}
			}

			@Override
			protected Editor<?> createFilter() {
				return null;
			}

			@Override
			protected TableModel<T> createTableModel() {
				return TableModelBuilder.createTableModel(entityClass);
			}

			@Override
			protected JPanel createStatus() {
				return null;
			}
		};
	}
}
